home *** CD-ROM | disk | FTP | other *** search
- Path: keats.ugrad.cs.ubc.ca!not-for-mail
- From: c2a192@ugrad.cs.ubc.ca (Kazimir Kylheku)
- Newsgroups: comp.lang.c
- Subject: Re: 2d array of pointers to structures ?
- Date: 15 Apr 1996 08:27:16 -0700
- Organization: Computer Science, University of B.C., Vancouver, B.C., Canada
- Message-ID: <4ktpskINNrmc@keats.ugrad.cs.ubc.ca>
- References: <829573448snz@willen.demon.co.uk>
- NNTP-Posting-Host: keats.ugrad.cs.ubc.ca
-
- In article <829573448snz@willen.demon.co.uk>,
- Adrian Parker <adrian@willen.demon.co.uk> wrote:
- >
- >I need to keep a 2d array of structures, which I have to do at runtime
- >as they array could be quite big, and the compiler can't cope with
- >static arrays of the required size.
- >
- >Say I have a structure of..
- >
- > typedef struct {
- > int id;
- > long colour;
- > } T_loc;
- > T_loc *locptr;
- >
- >And two variables containing the number of rows and colums. How do I
- >allocate the storage for the memory array, and how then do I reference
- >it ?
-
- This is up to your fancy, and should probably be determined by the sort of ways
- in which you will want to operate on the structure. If you choose a
- representation that's easy to implement, it may not easily support operations
- whose requirement was not initially forseen.
-
- >I know I need to allocate a pointer for each row, so..
- >
- > locptr = (T_loc *)malloc(rows);
- >
- >should allocate enough space to hold "rows" number of T_loc pointers.
-
- No. No cast is necessary, and the argument should be (rows * sizeof(T_loc *))
-
- The type of locptr should be:
-
-
- T_loc **locptr;
-
- Because you want it to be a pointer to the first element of an array of
- pointers, or a pointer to a pointer.
-
- >Then in each entry, I need to store a pointer to an array of columns..
- >which is where I'm stuck..
- >
- > for (x = 0 ; x < rows ; x++)
- > {
- > *(locptr+x) = (T_loc)malloc(cols);
-
- You may wish to use an equivalent array notation here: locptr[x]. But that is
- personal preference.
-
- > }
-
- The reason it doesn't work is twofold.
-
- Firstly, you are incorrectly casting the (void *) return type from malloc() to
- a (T_loc). The latter is not a pointer type, but a structure type. You want to
- cast to a (T_loc *).
-
- However: In ANSI C, you don't have to (and shouldn't) cast a (void *) type.
- Just do the assignment! The cast can hide a potential error:
-
- Suppose you forget to include the <stdlib.h> error, and your compiler
- hence doesn't have a prototype for malloc. It will assume that
- the return value is int. By putting a cast there, you occlude the
- possibility that a warning message will catch the error.
-
-
- Secondly, you are not giving the appropriate allocation size. If you want to
- allocate a number of structures equal to cols, the number of bytes you need is
- equivalent to cols * number of bytes in a T_loc.
-
- The correct statement is, therefore:
-
-
- *(locptr + x) = malloc(cols * sizeof(T_loc)); /* That's it! */
-
- >which I think should malloc "cols" number of T_loc variables, and store
- >the returned pointer in the 'x'th locptr pointer array.. but obviously
- >something is wrong as it won't compile.
-
- The above correction should take care of that.
-
- >I then need to be able to refer to a specific struct items for a
- >specific column in a specific row..
- >
- > (T_loc *)((*(locptr+ROW))+COL)->id
- >
- >or am I way off here too ?
-
- Sort of. First of all, no cast is needed to do this, because everything has the
- right type. Secondly, in the above expression, the -> operator has a higher
- precedence than the ( ) cast. So what you are doing is casting the id element
- to a (T_loc *), which is probably not what you want.
-
- You have an extra set of braces around the *(locptr+ROW) which are not needed,
- since * has a much higher precedence over the subsequent + COL.
-
- A table of operator precedences appears in K&R2, page 53.
-
- The correct expression is:
-
- ( *(locptr + ROW) + COL)) -> id
-
- Which is the same as
-
- ( *(*(locptr + ROW) + COL) ) . id
-
- Which is the same as
-
- ( *( locptr[ROW] + COL) ) . id
-
- which is just
-
- ( locptr[ROW][COL] ) . id
-
- Which is
-
- locptr[ROW][COL].id /* [] has same prededence level as . */
- /* in left to right associativity */
-
- Surprise! Thanks to C's treatment of arrays and pointers, it's the same
- expression that you would have used had you been able to declare a full
- two-dimensional array!
-
- A person reading your source cannot infer the type of ``locptr'' just by
- looking at the usage. According to the expression in which it is used, it could
- be any one of _four_ possibilities: a two-dimensional array of structures, a
- pointer to the first of an array of one-dimensional arrays of structures, a
- pointer to the first element of an array of pointers to allocated blocks of
- structures (your case), or an array of pointers to allocated structures.
- --
- I'm not really a jerk, but I play one on Usenet.
-